package com.dd.keel.core.common.utils;

import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import java.util.List;
import java.util.LinkedList;
import java.util.Arrays;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FileUtil {
	
	final static private Logger LOGGER = LoggerFactory.getLogger(FileUtil.class);
	
	public static boolean exists(String localFilePath)
	{
		File file = new File(localFilePath);
		return file.exists();
	}
	
	public static String backupFile(String localFilePath) throws Exception
	{
		if(localFilePath==null) return null;
		String[] tempArray = parseFileName(localFilePath);
		String backupFilePath = tempArray[0] + "/" + tempArray[1].replaceAll("\\.", "_") + "_bak_" + RandomUtil.randomInt(99999);
		LOGGER.debug("Backup file {} into {}", localFilePath, backupFilePath);
		FileUtil.copyFile(localFilePath, backupFilePath);
		return backupFilePath;
	}
	
	public static String retrieveConfigFilepath(String fileName)
	{
		String keel_home = EtcConfig.getKeelHomePath();
		String config_file = keel_home + "/etc/"+ fileName;
		return config_file;
	}
	
	public static String retrieveTempFilepath(String fileName)
	{
		String keel_home = EtcConfig.getKeelHomePath();
		String config_file = keel_home + "/logs/"+ fileName;
		return config_file;
	}
	
	public static void appendTextToFile(String text,String fileName,String charSet)
	{
		try{
			appendByteToFile(text.getBytes(charSet),fileName,1024);
		}catch(Exception ex){
			LOGGER.error( ex.getMessage(), ex );
		}
	}
	
	/**
	 * 从文件读字符串
	 * @param fileName
	 * @param charSet -> charset name
	 * @return
	 */
	public static String readTextFromFile(String fileName,String charSet)
	{
		try{
			byte[] temp = readByteFromFile(fileName);
			return new String(temp,charSet);
		}catch(Exception ex){
			LOGGER.error( ex.getMessage(), ex );
		}
		//return sb.toString();
		return null;
	}
	
	/**
	 * 写字符串到文件(覆盖)
	 * @param text
	 * @param fileName
	 * @param charSet
	 */
	public static void writeTextToFile(String text,String fileName,String charSet)
	{
		try{
			writeByteToFile(text.getBytes(charSet),fileName);
		}catch(Exception ex){
			LOGGER.error( ex.getMessage(), ex );
		}
	}
	
	public static byte[] readByteFromFile(String fileName) throws Exception
	{
		byte[] temp = null;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		FileInputStream fis = null;
		try{
			fis = new FileInputStream(fileName);
			byte[] buffer = new byte[1024];
			int count= 0;
			while( (count=fis.read(buffer))>0 )
			{
				baos.write(buffer, 0, count);
			}
			temp = baos.toByteArray();
		}catch(Exception ex){
			LOGGER.error( ex.getMessage(), ex );
			throw ex;
		}finally{
			try{
				fis.close();
				baos.close();
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		return temp;
	}
	
	public static byte[] readByteFromInputStream(InputStream inputStream) throws Exception
	{
		byte[] temp = null;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		try{
			byte[] buffer = new byte[1024];
			int count= 0;
			while( (count=inputStream.read(buffer))>0 )
			{
				baos.write(buffer, 0, count);
			}
			temp = baos.toByteArray();
		}catch(Exception ex){
			LOGGER.error( ex.getMessage(), ex );
			throw ex;
		}finally{
			try{
				baos.close();
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		return temp;
	}
	
	public static byte[] readByteFromClassFile(String fileName) throws Exception
	{
		byte[] temp = null;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		InputStream is = null;
		try{
			is = URLUtil.getURLFromClasspath(fileName).openStream();
			byte[] buffer = new byte[1024];
			int count= 0;
			while( (count=is.read(buffer))>0 )
			{
				baos.write(buffer, 0, count);
			}
			temp = baos.toByteArray();
		}catch(Exception ex){
			LOGGER.error( ex.getMessage(), ex );
			throw ex;
		}finally{
			try{
				is.close();
				baos.close();
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		return temp;
	}
	
	public static void writeByteToFile(byte[] byteArray, String fileName) throws Exception
	{
		writeByteToFile(byteArray,fileName,1024);
	}
	
	public static void writeByteToFile(byte[] byteArray, String fileName, int bufferSize) throws Exception
	{
		writeByteToFile(byteArray,0,byteArray.length,fileName,bufferSize);
	}
	
	public static void writeByteToFile(byte[] byteArray, int off, int len, String fileName, int bufferSize) throws Exception
	{
		if(byteArray==null) return;
		//LOGGER.log(LogService.LOG_DEBUG, "write data to file : "+fileName);
		ByteArrayInputStream bais = new ByteArrayInputStream(byteArray,off,len);
		makeSureDirectory(fileName);
		FileOutputStream fos = new FileOutputStream(fileName);
		byte[] buffer = new byte[bufferSize];
		int count= 0;
		while( (count=bais.read(buffer))>0 )
		{
			fos.write(buffer, 0, count);
		}
		fos.close();
		bais.close();
	}
	
	public static void appendByteToFile(byte[] byteArray, String fileName, int bufferSize) throws Exception
	{
		if(byteArray==null) return;
		ByteArrayInputStream bais = new ByteArrayInputStream(byteArray);
		try{
			makeSureDirectory(fileName);
			FileOutputStream fos = new FileOutputStream(fileName,true);
			byte[] buffer = new byte[bufferSize];
			int count= 0;
			while( (count=bais.read(buffer))>0 )
			{
				fos.write(buffer, 0, count);
			}
			fos.close();
			bais.close();
		}catch(Exception ex){
			LOGGER.error( ex.getMessage(), ex );
			throw ex;
		}
	}
	
	public static List<String> getFileNames(String directoryPath)
	{
		if(directoryPath==null) return null; 
		List<String> filePaths = new LinkedList<String>();
		File file = new File(directoryPath);
		if(file.exists() && file.isDirectory())
		{
			File[] files = file.listFiles( new RegexFileFilter(null) );
			//Arrays.sort(files, new CompratorByLastModified());
			if(files!=null && files.length>0)
			{
				for(int i=0; i<files.length; ++i )
				{
					String tempName = files[i].getAbsolutePath();
					filePaths.add( tempName );
				}
			}
		}
		return filePaths;
	}
	
	public static List<String> getFileNames(String directoryPath, String fileNamePattern)
	{
		if(directoryPath==null) return null; 
		List<String> filePaths = new LinkedList<String>();
		File file = new File(directoryPath);
		if(file.exists() && file.isDirectory())
		{
			File[] files = file.listFiles( new RegexFileFilter(fileNamePattern) );
			//Arrays.sort(files, new CompratorByLastModified());
			if(files!=null && files.length>0)
			{
				for(int i=0; i<files.length; ++i )
				{
					String tempName = files[i].getAbsolutePath();
					filePaths.add( tempName );
				}
			}
		}
		return filePaths;
	}
	
	public static boolean isExists(String fileNamePath)
	{
		File file = new File(fileNamePath);
		return file.exists();
	}
	
	public static List<String> getFileNames(String directoryPath, int max_file_count)
	{
		List<String> filePaths = getFileNames(directoryPath);
		if(filePaths!=null)
		{
			return limitFilePathNames(filePaths,max_file_count);
		}
		else
		{
			return new LinkedList<String>();
		}
	}
	
	public static List<String> getFileNames(String directoryPath, int max_file_count, String fileNamePattern)
	{
		List<String> filePaths = getFileNames(directoryPath,fileNamePattern);
		if(filePaths!=null)
		{
			return limitFilePathNames(filePaths,max_file_count);
		}
		else
		{
			return new LinkedList<String>();
		}
	}
	
	public static List<String> limitFilePathNames(List<String> filePathNames, int maxFileCount)
	{
		if(filePathNames!=null && !filePathNames.isEmpty())
		{
			if(filePathNames.size() > maxFileCount)
			{
				return filePathNames.subList(0, maxFileCount);
			}
			else
			{
				return filePathNames;
			}
		}
		else
		{
			return new LinkedList<String>();
		}
	}
	
	public static boolean deleteFile(String filePath) throws Exception
	{
		LOGGER.debug( "delete file {}", filePath);
		boolean flag = true;
		try{
			File file = new File(filePath);
			if(file.exists())
			{
				flag = file.delete();
			}
		}catch(Exception ex){
			LOGGER.error( ex.getMessage(), ex );
			flag = false;
			throw ex;
		}
		return flag;
	}
	
	public static String[] parseFileName(String sourceFileName)
	{
		if(sourceFileName==null) return null;
		sourceFileName = sourceFileName.replaceAll( "\\\\", "/" );
		String[] temp = new String[2];
		int sep_pos = sourceFileName.lastIndexOf("/");
		if(sep_pos==-1)
		{
			temp[0] = "";
			temp[1] = sourceFileName;
			return temp;
		}
		String pathDirectory = sourceFileName.substring(0,sep_pos);
		String fileName = sourceFileName.substring(sep_pos+1);
		temp[0] = pathDirectory.trim();
		temp[1] = fileName.trim();
		return temp;
	}
	
	public static void makeSureDirectory(String fileName) throws Exception
	{
		if(fileName==null) throw new Exception("No file path !");
		try{
			String[] temp = parseFileName(fileName);
			String pathDirectory = temp[0];
			if(pathDirectory.equals("")) return;
			File directory = new File(pathDirectory);
			if(!directory.exists()){
				directory.mkdirs();
			}else{
			}
		}catch(Exception ex){
			LOGGER.error( ex.getMessage(), ex );
			throw ex;
		}
	}
	
	public static void copyFile(String source, String dest) throws Exception
	{
		LOGGER.debug( "copy file {} to {}", source, dest);
		FileInputStream fis = null;
		FileOutputStream fos = null;
		try {
			makeSureDirectory(dest);
			fis = new FileInputStream(source);
			fos = new FileOutputStream(dest);
			byte[] buf = new byte[4096];
			int i = 0;
			while ((i = fis.read(buf)) != -1) {
				fos.write(buf, 0, i);
			}
		} catch (IOException ex) {
			LOGGER.error( ex.getMessage(), ex );
			throw ex;
		}finally{
			if(fis!=null) fis.close();
			if(fos!=null) fos.close();
		}
	}
	
	public static void moveFileToDirectory(String sourceFileName, String destDirectoryName, boolean createDestDir, boolean overwriteExistedFile) throws Exception
	{
		if( sourceFileName == null || destDirectoryName == null ){
			throw new IllegalArgumentException("No specified file !! ");
		}
		try {
			String[] temp = parseFileName(sourceFileName);
			String fileName = temp[1];
			if(createDestDir){
				makeSureDirectory(destDirectoryName);
			}
			if(overwriteExistedFile){
				copyFile(sourceFileName, destDirectoryName + "/"+ fileName );
				deleteFile(sourceFileName);
			}else{
				String newSourceFile = fileName + "." + RandomUtil.randomInt(9999);
				copyFile(sourceFileName, destDirectoryName+ "/" + newSourceFile );
				deleteFile(sourceFileName);
			}
		} catch (Exception ex) {
			LOGGER.error( ex.getMessage(), ex );
			throw ex;
		}
	}
	
}
